package com.topdt.jbpm.web.servlet;

import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Date;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializeConfig;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.alibaba.fastjson.serializer.SimpleDateFormatSerializer;
import com.thx.common.util.AppContext;
import com.thx.common.util.ThreadLocalContext;
import com.thx.common.web.ActionResult;
import com.thx.common.web.SessionInfo;
import com.thx.common.web.WebConstant;
import com.topdt.jbpm.Constants;
import com.topdt.jbpm.identity.IdFactory;
import com.topdt.jbpm.identity.IdentityService;
import com.topdt.jbpm.identity.User;
import com.topdt.jbpm.service.AttachmentService;
import com.topdt.jbpm.service.JbpmService;
import com.topdt.jbpm.web.servlet.action.JbpmAction;

public class JbpmServlet extends HttpServlet {

	private static final long serialVersionUID = 1L;

	private static Logger LOG = LoggerFactory.getLogger(JbpmServlet.class);

	@Override
	public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
		try {
			process(request, response);
		} catch (Exception ex) {
			errorResp(response,"服务端异常");
			throw new ServletException(ex);
		}
	}

	@Override
	public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
		try {
			process(request, response);
		} catch (Exception ex) {
			errorResp(response,"服务端异常");
			throw new ServletException(ex);
		}
	}

	public void process(HttpServletRequest request, HttpServletResponse response) throws Exception {

		request.setCharacterEncoding("utf-8");
		response.setCharacterEncoding("utf-8");

		String contextPath = request.getContextPath();
		String servletPath = request.getServletPath();
		String requestURI = request.getRequestURI();

		String path = requestURI.substring(contextPath.length() + servletPath.length() + 1);

		String action = path;
		SessionInfo sessionInfo = (SessionInfo) request.getSession().getAttribute(WebConstant.KEY_USER);
		User user = getIdService().getUserById(sessionInfo.getUserId());
		if (user == null) {
			response.sendRedirect(contextPath + "/index.jsp");
			return;
		}

		ThreadLocalContext.set(Constants.CONTEXT_HTTPREQ, request);
		ThreadLocalContext.set(AppContext.CURRENT_COM_ID, sessionInfo.getComId());
		ThreadLocalContext.set(Constants.SESSIONID_KEY, request.getSession().getId());
		ThreadLocalContext.set(Constants.USER_KEY, user);
		try {

			String[] actions = path.split("/");
			if (actions.length == 1) {
				Class<? extends JbpmServlet> clz = this.getClass();
				Method method = clz.getDeclaredMethod(action, HttpServletRequest.class, HttpServletResponse.class);
				method.invoke(this, request, response);
			} else if (actions.length == 2) {
				JbpmAction actionObj = this.getAction(actions[0]);
				actionObj.execute(actions[1], request, response);
			} else
				response.getWriter().write("no mapping resource: " + path);
		} catch (Exception ex) {
			ex.printStackTrace();
			errorResp(response,"服务端异常");
		}

	}

	public void responseJson(HttpServletResponse response, Object jsonObj) throws IOException {
		response.setContentType(Constants.CONTENT_TYPE_TEXT);
		String resp = JSON.toJSONString(jsonObj,SerializerFeature.WriteDateUseDateFormat);
		LOG.debug(resp);
		response.getWriter().write(resp);
	}

	public void responseJson(HttpServletResponse response, String json) throws IOException {
		response.setContentType(Constants.CONTENT_TYPE_TEXT);
		response.getWriter().write(json);
	}

	public void responseError(HttpServletResponse response, String message) throws IOException {
		response.setContentType(Constants.CONTENT_TYPE_TEXT);
		response.getWriter().write(message);
	}

	public void responseJsp(HttpServletRequest request, HttpServletResponse response, String path) throws ServletException, IOException {
		RequestDispatcher dispatcher = request.getRequestDispatcher(path);
		dispatcher.forward(request, response);

	}

	public void responseRedirec(HttpServletRequest request, HttpServletResponse response, String path) throws ServletException, IOException {
		response.sendRedirect(path);
	}

	private JbpmAction getAction(String action) {

		String packageName = "com.topdt.jbpm.web.servlet.action.";

		String className = (new StringBuilder()).append(packageName).append(Character.toUpperCase(action.charAt(0))).append(action.substring(1)).append("Action").toString();
		try {
			Class clazz = Class.forName(className);
			Constructor constructor = clazz.getConstructor(JbpmServlet.class);
			JbpmAction actionObj = (JbpmAction) constructor.newInstance(this);
			return actionObj;
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} catch (NoSuchMethodException e) {
			e.printStackTrace();
		} catch (SecurityException e) {
			e.printStackTrace();
		} catch (InstantiationException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			e.printStackTrace();
		}

		return null;

	}

	private JbpmService jbpmService;// 不能在方法中直接使用此，要通过get方法获取

	public JbpmService getJbpmService() {
		if (jbpmService == null) {
			jbpmService = JbpmService.getJbpmService();
		}
		return jbpmService;
	}

	private IdentityService idService;// 不能在方法中直接使用此，要通过get方法获取

	public IdentityService getIdService() {
		if (idService == null)
			idService = IdFactory.getIdentityServiceFactory().getIdentityService();
		return idService;
	}

	private AttachmentService attachmentService;

	public AttachmentService getAttachmentService() {
		if (attachmentService == null)
			attachmentService = AttachmentService.getAttachmentService();
		return attachmentService;
	}

	private void errorResp(HttpServletResponse resp, String message) {
		ActionResult result = new ActionResult(ActionResult.FAIL, message);
		try {
			this.responseJson(resp, result);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

}
